class MyPromise {
  constructor(excute) {
    this.state = "pending";
    this.value = "";
    this.reason = "";

    this.onFulfilledFns = [];
    this.onRejectedFns = [];

    const resolve = (value) => {
      if (this.state === "pending") {
        setTimeout(() => {
          this.state = "fulfilled";
          this.value = value;
          this.onFulfilledFns.forEach((f) => f(value));
        });
      }
    };

    const reject = (reason) => {
      if (this.state === "pending") {
        setTimeout(() => {
          this.state = "rejected";
          this.reason = reason;
          this.onRejectedFns.forEach((f) => f(reason));
        });
      }
    };

    try {
      excute(resolve, reject);
    } catch (err) {
      reject(err);
    }
  }

  /**
   * 
   * @param {*} onFulfilled 
   * @param {*} onRejected 
   * 
   *  * then方法，promise需要一个then方法接受fulfilled状态和rejected状态执行返回的参数，then方法遵循以下规则
    接收两个回调函数参数
    传入的两个回调函数是异步执行的，要在下一次事件循环过程中执行
    then方法的返回值是promise
    then可以被同一个promise多次调用
   */
  then(onFulfilled, onRejected) {
    let x;
    let promise;
    // then方法也会返回一个promise对象
    if (this.state === "fulfilled") {
      promise = new MyPromise((resolve, reject) => {
        setTimeout(() => {
          x = onFulfilled(this.value);
          resolvePromise(x, promise, resolve, reject);
        });
      });
    } else if (this.state === "rejected") {
      promise = new MyPromise((resolve, reject) => {
        try {
          setTimeout(() => {
            x = onRejected(this.reason);
            resolvePromise(x, promise, resolve, reject);
          });
        } catch (err) {
          reject(err);
        }
      });
    } else if (this.state === "pending") {
      this.onFulfilledFns.push(() => {
        setTimeout(() => {
          x = onFulfilled(this.value);
          resolvePromise(x, promise, resolve, reject);
        });
      });
      this.onRejectedFns.push(() => {
        setTimeout(() => {
          x = onRejected(this.reason);
          resolvePromise(x, promise, resolve, reject);
        });
      });
    }

    return promise;
  }

  catch(onError) {
    this.then(null, (reason) => {
      onError(reason);
    });
  }
  finally(onFinally) {
    this.then(
      (value) => {
        MyPromise.resolve(onFinally()).then(() => {
          return value;
        });
      },
      (reason) => {
        MyPromise.reject(onFinally()).then(() => {
          throw reason;
        });
      }
    );
  }
}

MyPromise.resolve = function (value) {
  if (value instanceof MyPromise) {
    return value;
  }
  return new MyPromise((resolve) => {
    return resolve(value);
  });
};

MyPromise.reject = function (reason) {
  return new MyPromise((resolve, reject) => {
    reject(reason);
  });
};

// all 返回执行结果集和数组
MyPromise.all = function (array) {
  return new MyPromise((resolve, reject) => {
    if (!(array instanceof Array)) {
      resolve([]);
      return;
    }

    const result = [];
    const len = array.length;
    for (let i = 0; i < len; i++) {
      const task = array[i];
      MyPromise.resolve(task).then(
        (value) => {
          result[i] = value;
        },
        (err) => {
          reject(err);
        }
      );
    }
    resolve(result);
  });
};

// race 看谁第一个冲出来
MyPromise.race = function (array) {
  return new MyPromise((resolve, reject) => {
    if (!(array instanceof Array)) {
      resolve([]);
    }

    const len = array.length;
    for (let i = 0; i < len; i++) {
      const task = array[i];
      MyPromise.resolve(task).then(
        (value) => {
          resolve(value);
        },
        (reason) => {
          reject(reason);
        }
      );
    }
  });
};

// any
MyPromise.any = function (array) {
  return new MyPromise((resolve, reject) => {
    if (!(array instanceof Array)) {
      return resolve([]);
    }

    const reasons = [];
    const len = array.length;
    for (let i = 0; i < len; i++) {
      const task = array[i];
      MyPromise.resolve(task).then(
        (value) => {
          return resolve(value);
        },
        (reason) => {
          reasons[i] = reason;
        }
      );
    }
    reject(reasons);
  });
};

function resolvePromise(x, promise, resolve, reject) {
  if (x === promise) {
    throw Error("不能返回自己");
  }

  if (x !== null && (typeof x === "function" || typeof x === "object")) {
    // thenable对象
    const then = x.then;
    if (typeof then === "function") {
      // 加一把锁
      let excuted = false;
      try {
        then.call(
          x,
          (y) => {
            if (!excuted) {
              excuted = true;
              resolve(y);
            }
          },
          (errr) => {
            if (!excuted) {
              excuted = true;
              reject(errr);
            }
          }
        );
      } catch (err) {
        reject(err);
      }
    } else {
      resolve(x);
    }
  } else {
    resolve(x);
  }
}
